import { observe } from './observer/index.js'
import Watcher from './observer/watcher'
export function stateMixin(Vue){
    Vue.prototype.$watch = function(key,handler,options = {}){
        let vm = this
        options.user = true
        new Watcher(vm,key,handler,options)
    }
}
export function initState(vm){
    const options = vm.$options
    if(options.props){
        initProps(vm)
    }
    if(options.methods){
        initMethods(vm)
    }
    if(options.data){
        initData(vm)
    }
    if(options.computed){
        initComputed(vm)
    }
    if(options.watch){
        initWatch(vm)
    }  
}

function initProps(vm){
    
}


function initMethods(vm){
    
}


function proxyData(vm,source){
    for(let key in source){
        Object.defineProperty(vm,key,{
           get(){
               return source[key]
           },
           set(newVal){
              source[key] = newVal
           }
       })
    }
}

function initData(vm){
    let data = vm.$options.data
    data = typeof data === 'function'? data.call(vm) : data
    vm._data = data
    proxyData(vm,vm._data)
    observe(data)
}


function initComputed(vm){
    let computed = vm.$options.computed
    vm._computed = {}
    for(let key in computed){
        let getter = computed[key]
        vm._computedWatchers[key] = new Watcher(vm,getter,()=>{},{lazy:true})
        createComputed(vm,key)
    }
}
function createComputed(vm,key){
    Object.defineProperty(vm,key,{
        get(){
            let watcher = this._computedWatchers[key]
            if(watcher.dirty){
                watcher.evaluate()
            }
            // TODO
            return watcher.value
        }
    })
}


function initWatch(vm){
    let watch = vm.$options.watch
    for(let key in watch){
       let handler  = watch[key]
       vm.$watch(key,handler)
    }
}
